package message

import (
	"bytes"
	"encoding/binary"
	"errors"
)

// PacketMaxSize 默认最大包大小 1MB
const PacketMaxSize = 1024 * 1024

var GlobalCoder = NewCoder(PacketMaxSize)

// Coder 消息编解码器
type Coder struct {
	maxPacketSize uint32 // 最大包大小
}

// NewCoder 创建一个新的编解码器
func NewCoder(maxPacketSize uint32) *Coder {
	if maxPacketSize == 0 {
		maxPacketSize = PacketMaxSize
	}
	return &Coder{
		maxPacketSize: maxPacketSize,
	}
}

// GetHeadLen 获取消息头长度
func (c *Coder) GetHeadLen() uint32 {
	return 8 // DataLen(4) + Id(4)
}

// Decode 解码消息
func (c *Coder) Decode(data []byte) (IMessage, error) {
	dataBuff := bytes.NewReader(data)

	msg := &Message{}

	// 读取dataLen
	if err := binary.Read(dataBuff, binary.LittleEndian, &msg.DataLen); err != nil {
		return nil, err
	}

	// 读取消息ID
	if err := binary.Read(dataBuff, binary.LittleEndian, &msg.Id); err != nil {
		return nil, err
	}

	// 判断数据包大小是否超出限制
	if msg.DataLen > c.maxPacketSize {
		return nil, errors.New("too large msg data received")
	}

	// 读取消息数据
	if msg.DataLen > 0 {
		msg.Data = make([]byte, msg.DataLen)
		if err := binary.Read(dataBuff, binary.LittleEndian, msg.Data); err != nil {
			return nil, err
		}
	}

	return msg, nil
}

// Encode 编码消息
func (c *Coder) Encode(msg IMessage) ([]byte, error) {
	dataBuff := bytes.NewBuffer([]byte{})

	// 写入dataLen
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetDataLen()); err != nil {
		return nil, err
	}

	// 写入消息ID
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetMsgId()); err != nil {
		return nil, err
	}

	// 写入消息数据
	if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetData()); err != nil {
		return nil, err
	}

	return dataBuff.Bytes(), nil
}
